#include "serialport.h"

#include <print>
#include <sstream>
#include <stdexcept>
#include <boost/system/system_error.hpp>

// Windows平台额外头文件
#ifdef _WIN32
#include <windows.h>
#endif

SerialPort::SerialPort(const std::string& port_name, int baud_rate,
    int parity, int databit, int stopbit)
    : pSerialPort(std::make_unique<boost::asio::serial_port>(m_ios)),
    m_port(port_name),
    m_baudRate(baud_rate),
    m_parity(parity),
    m_dataBits(databit),
    m_stopBits(stopbit),
    m_isReading(false),
    m_isStopping(false)
{
    try {
        m_work = std::make_unique<decltype(m_work)::element_type>(
            boost::asio::make_work_guard(m_ios)
        );

        // 启动IO线程并强化异常捕获
        m_ioThread = std::thread([this]() {
            try {
                m_ios.run();
            }
            catch (const boost::system::system_error& e) {
                std::println("串口IO线程系统异常: {} (错误码: {})",
                    e.what(), e.code().value());
            }
            catch (const std::exception& e) {
                std::println("串口IO线程异常: {}", e.what());
            }
            catch (...) {
                std::println("串口IO线程发生未知异常");
            }
            });

        // 检查初始化结果
        if (!init_port(port_name, baud_rate, parity, databit, stopbit)) {
            std::println("串口初始化未完全成功，端口: {}", port_name.c_str());
        }
    }
    catch (const std::exception& e) {
        std::println("串口构造函数异常: {}", e.what());
        throw; // 向上传播构造失败
    }
}

SerialPort::~SerialPort()
{
    StopReading();

    try {
        if (pSerialPort && pSerialPort->is_open()) {
            pSerialPort->cancel();
            pSerialPort->close();
        }
    }
    catch (const boost::system::system_error& e) {
        std::println("析构函数关闭串口系统错误: {} (错误码: {})",
            e.what(), e.code().value());
    }
    catch (const std::exception& e) {
        std::println("析构函数关闭串口错误: {}", e.what());
    }
    catch (...) {
        std::println("析构函数关闭串口发生未知错误");
    }

    if (!m_ios.stopped()) {
        m_ios.stop();
    }
    if (m_ioThread.joinable()) {
        m_ioThread.join();
    }
}

bool SerialPort::IsOpen() const
{
    // 检查串口对象是否存在、是否打开以及参数是否有效
    return pSerialPort != nullptr && pSerialPort->is_open() && m_paramsValid;
}


bool SerialPort::init_port(const std::string& port_name, int baud_rate,
    int parity, int databit, int stopbit)
{
    if (!this || !pSerialPort) {
        std::println("初始化失败: 无效的对象或串口指针");
        return false;
    }

    try {
        if (pSerialPort->is_open()) {
            pSerialPort->close();
        }

        // 打开串口（带错误码检查）
        pSerialPort->open(port_name, m_ec);
        if (m_ec) {
            std::println("无法打开串口 {}: {} (错误码: {})",
                port_name.c_str(), m_ec.message().c_str(), m_ec.value());
            return false;
        }

        // 配置波特率
        pSerialPort->set_option(boost::asio::serial_port_base::baud_rate(baud_rate), m_ec);
        if (m_ec) {
            std::println("设置波特率失败: {} (错误码: {})", m_ec.message().c_str(), m_ec.value());
            return false;
        }

        // 配置校验位
        boost::asio::serial_port_base::parity::type parityType;
        switch (parity) {
        case 0: parityType = boost::asio::serial_port_base::parity::none; break;
        case 1: parityType = boost::asio::serial_port_base::parity::even; break;
        case 2: parityType = boost::asio::serial_port_base::parity::odd; break;
        default:
            std::println("无效的校验位配置: {}", parity);
            return false;
        }
        pSerialPort->set_option(boost::asio::serial_port_base::parity(parityType), m_ec);
        if (m_ec) {
            std::println("设置校验位失败: {} (错误码: {})", m_ec.message().c_str(), m_ec.value());
            return false;
        }

        // 配置数据位
        pSerialPort->set_option(boost::asio::serial_port_base::character_size(databit), m_ec);
        if (m_ec) {
            std::println("设置数据位失败: {} (错误码: {})", m_ec.message().c_str(), m_ec.value());
            return false;
        }

        // 配置停止位
        boost::asio::serial_port_base::stop_bits::type stopBitsType;
        switch (stopbit) {
        case 1: stopBitsType = boost::asio::serial_port_base::stop_bits::one; break;
        case 2: stopBitsType = boost::asio::serial_port_base::stop_bits::two; break;
        default:
            std::println("无效的停止位配置: {}", stopbit);
            return false;
        }
        pSerialPort->set_option(boost::asio::serial_port_base::stop_bits(stopBitsType), m_ec);
        if (m_ec) {
            std::println("设置停止位失败: {} (错误码: {})", m_ec.message().c_str(), m_ec.value());
            return false;
        }

        m_paramsValid = true;
        std::println("串口 {} 初始化成功", port_name.c_str());
        return true;
    }
    catch (const boost::system::system_error& e) {
        std::println("串口初始化系统错误: {} (错误码: {})", e.what(), e.code().value());
    }
    catch (const std::exception& e) {
        std::println("串口初始化异常: {}", e.what());
    }
    catch (...) {
        std::println("串口初始化发生未知异常");
    }
    m_paramsValid = false;
    return false;
}

void SerialPort::Close()
{
    m_isStopping = true;

    // 取消异步操作
    try {
        if (pSerialPort && pSerialPort->is_open()) {
            pSerialPort->cancel(m_ec);
            if (m_ec) {
                std::println("取消异步操作失败: {} (错误码: {})", m_ec.message().c_str(), m_ec.value());
            }
        }
    }
    catch (const boost::system::system_error& e) {
        std::println("取消异步操作系统错误: {} (错误码: {})", e.what(), e.code().value());
    }
    catch (const std::exception& e) {
        std::println("取消异步操作错误: {}", e.what());
    }

    // 关闭串口
    try {
        if (pSerialPort && pSerialPort->is_open()) {
            pSerialPort->close(m_ec);
            if (m_ec) {
                std::println("关闭串口失败: {} (错误码: {})", m_ec.message().c_str(), m_ec.value());
            }
        }
    }
    catch (const boost::system::system_error& e) {
        std::println("关闭串口系统错误: {} (错误码: {})", e.what(), e.code().value());
    }
    catch (const std::exception& e) {
        std::println("关闭串口错误: {}", e.what());
    }
}

void SerialPort::write_to_serial(const std::string& data, bool hex)
{
    if (!pSerialPort || !IsOpen() || m_isStopping) {
        std::println("写入失败: 串口未打开或正在停止");
        return;
    }

    std::vector<unsigned char> buffer;

    try {
        if (hex) {
            std::istringstream iss(data);
            std::string token;
            while (iss >> token) {
                // 支持0x前缀和纯数字格式
                if (token.substr(0, 2) == "0x") {
                    token = token.substr(2);
                }
                unsigned int value;
                std::istringstream converter(token);
                if (!(converter >> std::hex >> value) || converter.fail() || value > 0xFF) {
                    std::println("无效的HEX数据: {}", token.c_str());
                    if (m_errorCallback) {
                        m_errorCallback("无效的HEX数据: " + token);
                    }
                    continue;
                }
                buffer.push_back(static_cast<uint8_t>(value));
            }
        }
        else {
            buffer.assign(data.begin(), data.end());
        }

        // 加入发送队列
        std::lock_guard<std::mutex> lock(m_sendMutex);
        m_sendQueue.push(buffer);
        if (!m_isSending) {
            m_isSending = true;
            boost::asio::async_write(
                *pSerialPort,
                boost::asio::buffer(m_sendQueue.front()),
                [this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
                    this->handle_write(ec, bytes_transferred);
                }
            );
        }
    }
    catch (const std::exception& e) {
        std::println("数据转换或入队失败: {}", e.what());
        if (m_errorCallback) {
            m_errorCallback("写入数据处理失败: " + std::string(e.what()));
        }
    }
}

void SerialPort::handle_write(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
    if (m_isStopping) return;

    std::unique_lock<std::mutex> lock(m_sendMutex);
    if (!m_sendQueue.empty()) {
        m_sendQueue.pop();
    }
    bool hasNext = !ec && !m_sendQueue.empty();
    lock.unlock();

    try {
        if (hasNext) {
            lock.lock();
            const auto& nextData = m_sendQueue.front();
            lock.unlock();
            boost::asio::async_write(
                *pSerialPort,
                boost::asio::buffer(nextData),
                [this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
                    this->handle_write(ec, bytes_transferred);
                }
            );
        }
        else {
            lock.lock();
            m_isSending = false;
            lock.unlock();
            if (ec) {
                std::println("串口写入错误: {} (错误码: {})", ec.message().c_str(), ec.value());
                if (m_errorCallback) {
                    try {
                        m_errorCallback("写入错误: " + ec.message());
                    }
                    catch (const std::exception& e) {
                        std::println("错误回调抛出异常: {}", e.what());
                    }
                }
            }
            else {
                std::println("串口写入成功，字节数: %zu", bytes_transferred);
            }
        }
    }
    catch (const std::exception& e) {
        std::println("处理写入回调失败: {}", e.what());
    }
}

void SerialPort::StartReading(DataCallback dataCallback, ErrorCallback errorCallback)
{
    if (!pSerialPort || !IsOpen() || m_isReading || m_isStopping) {
        std::println("启动读取失败: 串口状态异常");
        return;
    }

    // 防止重复启动
    if (m_isReading.exchange(true)) {
        std::println("启动读取失败: 已在读取中");
        return;
    }

    try {
        if (!clearBuffer()) {
            std::println("清空缓冲区失败，但继续启动读取");
        }

        m_dataCallback = dataCallback;
        m_errorCallback = errorCallback;
        m_isStopping = false;

        pSerialPort->async_read_some(
            boost::asio::buffer(m_readBuffer, sizeof(m_readBuffer)),
            [this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
                this->handle_read(ec, bytes_transferred);
            }
        );
        std::println("开始串口读取");
    }
    catch (const std::exception& e) {
        m_isReading = false;  // 异常时重置状态
        std::println("启动读取失败: {}", e.what());
        if (errorCallback) {
            errorCallback("启动读取失败: " + std::string(e.what()));
        }
    }
}

void SerialPort::StopReading()
{
    m_isStopping = true;
    m_isReading = false;

    try {
        if (pSerialPort && pSerialPort->is_open()) {
            pSerialPort->cancel(m_ec);
            if (m_ec) {
                std::println("取消读取操作失败: {}", m_ec.message().c_str());
            }
            pSerialPort->close(m_ec);
            if (m_ec) {
                std::println("停止时关闭串口失败: {}", m_ec.message().c_str());
            }
        }

        // 清空发送队列
        {
            std::lock_guard<std::mutex> lock(m_sendMutex);
            while (!m_sendQueue.empty()) {
                m_sendQueue.pop();
            }
            m_isSending = false;
        }

        m_partialData.clear();
        std::println("串口读取已停止");
    }
    catch (const boost::system::system_error& e) {
        std::println("停止读取系统错误: {} (错误码: {})", e.what(), e.code().value());
    }
    catch (const std::exception& e) {
        std::println("停止读取错误: {}, 串口: {}", e.what(), m_port.c_str());
        if (m_errorCallback) {
            try {
                m_errorCallback("停止错误: " + std::string(e.what()));
            }
            catch (...) {
                std::println("停止错误回调抛出异常");
            }
        }
    }
}

void SerialPort::ReadOnceAsync(DataCallback dataCallback, ErrorCallback errorCallback)
{
    if (!pSerialPort || !IsOpen() || m_isStopping) {
        //wxLogWarning("单次读取失败: 串口状态异常");
        return;
    }

    // 检查是否正在执行异步读取，若正在读取则忽略当前请求（核心逻辑）
    //if (m_isReadingAsync.exchange(true)) {
    //    //wxLogWarning("单次读取被忽略: 上一次读取尚未完成");
    //    if (errorCallback) {
    //        errorCallback("上一次读取尚未完成，已忽略当前请求");
    //    }
    //    return;
    //}

    try {
        pSerialPort->async_read_some(
            boost::asio::buffer(m_readBuffer, sizeof(m_readBuffer)),
            [this, dataCallback, errorCallback](const boost::system::error_code& ec, std::size_t bytes_transferred) {
                // 重置读取状态（无论成功/失败都需重置）
                m_isReadingAsync = false;

                if (m_isStopping) return;

                if (!ec && bytes_transferred > 0) {
                    std::string data(m_readBuffer, bytes_transferred);
                    if (dataCallback) {
                        try {
                            dataCallback(data);
                        }
                        catch (const std::exception& e) {
                        }
                    }
                }
                else if (errorCallback) {
                    try {
                        errorCallback("异步读取失败: " + ec.message());
                    }
                    catch (const std::exception& e) {
                    }
                }
            }
        );
    }
    catch (const std::exception& e) {
        // 异常时也需重置状态
        m_isReadingAsync = false;
        std::println("发起单次读取失败: {}", e.what());
        if (errorCallback) {
            errorCallback("发起单次读取失败: " + std::string(e.what()));
        }
    }
}

bool SerialPort::reopen_port(int new_baud_rate)
{
    try {
        bool wasReading = m_isReading;
        if (wasReading) {
            StopReading();
        }

        bool result = init_port(m_port, new_baud_rate, m_parity, m_dataBits, m_stopBits);
        if (!result) {
            std::println("重新打开串口失败，新波特率: {}", new_baud_rate);
            return false;
        }

        if (wasReading) {
            StartReading(m_dataCallback, m_errorCallback);
        }
        std::println("串口重新打开成功，新波特率: {}", new_baud_rate);
        return true;
    }
    catch (const std::exception& e) {
        std::println("重新打开串口异常: {}", e.what());
        return false;
    }
}

void SerialPort::handle_read(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
    if (!m_isReading || m_isStopping) return;

    try {
        if (!ec && bytes_transferred > 0) {
            std::string newData(m_readBuffer, bytes_transferred);
            process_received_data(newData);

            // 继续读取
            pSerialPort->async_read_some(
                boost::asio::buffer(m_readBuffer, sizeof(m_readBuffer)),
                [this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
                    this->handle_read(ec, bytes_transferred);
                }
            );
        }
        else {
            if (ec) {
                std::println("串口读取错误: {} (错误码: {})", ec.message().c_str(), ec.value());
                if (m_errorCallback) {
                    try {
                        m_errorCallback("读取错误: " + ec.message());
                    }
                    catch (const std::exception& e) {
                        std::println("读取错误回调异常: {}", e.what());
                    }
                }
            }
            StopReading();
        }
    }
    catch (const std::exception& e) {
        std::println("处理读取数据异常: {}", e.what());
        StopReading();
    }
}

void SerialPort::process_received_data(const std::string& data)
{
    if (m_dataCallback) {
        try {
            m_dataCallback(data);
        }
        catch (const std::exception& e) {
            std::println("数据回调函数异常: {}", e.what());
            if (m_errorCallback) {
                m_errorCallback("数据回调异常: " + std::string(e.what()));
            }
        }
        catch (...) {
            std::println("数据回调函数发生未知异常");
            if (m_errorCallback) {
                m_errorCallback("数据回调发生未知异常");
            }
        }
    }
}

bool SerialPort::clearBuffer()
{
    if (!IsOpen()) {
        std::println("清空缓冲区失败: 串口未打开");
        return false;
    }

#ifdef _WIN32
    HANDLE hComm = reinterpret_cast<HANDLE>(pSerialPort->native_handle());
    if (hComm == INVALID_HANDLE_VALUE) {
        std::println("清空缓冲区失败: 无效的串口句柄");
        return false;
    }
    // 清空接收和发送缓冲区
    BOOL result = PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR);
    if (!result) {
        DWORD err = GetLastError();
        std::println("清空缓冲区系统错误: 错误码 {}", err);
        return false;
    }
    return true;
#else
    // 非Windows平台可添加对应逻辑
    wxLogDebug("非Windows平台未实现缓冲区清空");
    return true;
#endif
}